import java.util.ArrayList;
import java.util.List;

/**
 * @modulename AssemblyListing
 * 
 * @description This class manages of all the information needed to create and
 *              keep track of an Assembly Listing table (see appendix C on page
 *              nine of the assignment specifications guide).
 * 
 * @callsequence AssemblyListing.startAssemblyListing();
 * 
 * @inparam none
 * 
 * @outparam creates a new AssemblyListing object
 * 
 * @errorstested See JUnit test cases
 * @errorsgenerated See errata report
 * @author Travis Casper
 * @createdate 11/5/09
 * @modlog <p>
 *         <ul>
 *         Who/When/Why
 *         <li>
 *         </ul>
 *         Coding Standards Met: "Signed Code Leader(Jaron)"
 *         <p>
 *         Testing Standards Met: "Signed Test Leader(Jamie)"
 */
public class AssemblyListing extends IntermediateFile {
	private static List<String> objectCodeArray;
	private static List<Integer> lineNumberArray;

	public static void startAssemblyListing() {
		objectCodeArray = new ArrayList<String>();
		lineNumberArray = new ArrayList<Integer>();
	}

	/**
	 * @modulename editRelocationCode
	 * @description Sets the Relocation Code for the line of code with the given
	 *              line number to the given Relocation Code.
	 * @callsequence <code>AssemblyListing.editRelocationCode(11, "C");</code>
	 * 
	 * @inparam lineNumber - An Integer that represents the line of code whose
	 *          Relocation Code will be edited.
	 *          <p>
	 *          relocationCode - A String that represents the new Relocation
	 *          Code that this line should use.
	 * @outparam none
	 * @errorstested See JUnit test cases
	 * @errorsgenerated See errata report
	 * @createdate 11/3/09
	 * @modlog <p>
	 *         <ul>
	 *         Who/When/Why
	 *         <li>
	 *         </ul>
	 *         Coding Standards Met: "Signed Code Leader(Jaron)"
	 *         <p>
	 *         Testing Standards Met: "Signed Test Leader(Jamie)"
	 */
	public static void editRelocationCode(Integer lineNumber, String relocationCode) {
		if (lineNumber >= relocationCodeArray.size()) {
			AssemblyListing.relocationCodeArray.add(relocationCode);
		} else {
			AssemblyListing.relocationCodeArray.add(lineNumber, relocationCode);
		}
	}

	/**
	 * @modulename editLocationCounter
	 * @description Sets the Location Counter for the line of code with the
	 *              given line number to the given Location Counter.
	 * @callsequence <code>AssemblyListing.editLocationCounter(11, 5);</code>
	 * 
	 * @inparam lineNumber - An Integer that represents the line of code whose
	 *          Location Counter will be edited.
	 *          <p>
	 *          LocationCounter - A String that represents the new Location
	 *          Counter that this line should use.
	 * @outparam none
	 * @errorstested See JUnit test cases
	 * @errorsgenerated See errata report
	 * @createdate 11/3/09
	 * @modlog <p>
	 *         <ul>
	 *         Who/When/Why
	 *         <li>
	 *         </ul>
	 *         Coding Standards Met: "Signed Code Leader(Jaron)"
	 *         <p>
	 *         Testing Standards Met: "Signed Test Leader(Jamie)"
	 */
	public static void editLocationCounter(Integer lineNumber, Integer locationCounter) {
		if (lineNumber >= locationCounterArray.size()) {
			AssemblyListing.locationCounterArray.add(locationCounter);
		} else {
			AssemblyListing.locationCounterArray.add(lineNumber, locationCounter);
		}
	}

	/**
	 * @modulename addObjectCode
	 * @description This Method adds the Object Code of the current line of
	 *              Source Code to that line's information in the
	 *              AssemblyListing Object. This Method is required to be run,
	 *              as each line of Source Code must have an Object Code.
	 *              However, this method cannot be run more than one time for
	 *              each line of code, as there will never be a case where there
	 *              will be more than one Object Code for a given line of source
	 *              code. REQUIRED, CALL ONCE.
	 * @callsequence
	 * 
	 * @inparam lineNumber - An Integer that represents the line number that the
	 *          Object Code will be added to.
	 *          <p>
	 *          objCode - A String that is the Binary Representation of the Word
	 *          of Data for the corresponding line
	 * @outparam none
	 * @errorstested See JUnit test cases
	 * @errorsgenerated See errata report
	 * @createdate 11/5/09
	 * @modlog <p>
	 *         <ul>
	 *         Who/When/Why
	 *         <li>
	 *         </ul>
	 *         Coding Standards Met: "Signed Code Leader(Jaron)"
	 *         <p>
	 *         Testing Standards Met: "Signed Test Leader(Jamie)"
	 */
	public static void addObjectCode(Integer lineNumber, String objCode) {
		AssemblyListing.objectCodeArray.add(objCode);
		AssemblyListing.lineNumberArray.add(lineNumber);
	}

	/**
	 * @modulename returnObjectCode
	 * @description This Method returns the Object Code of the current line of
	 *              Source Code as a String with the correct Hex Value
	 * @callsequence
	 * 
	 * @inparam lineNumber - An Integer that represents the line of code that
	 *          whose Object Code is to be returned. If there is no given Object
	 *          Code for that line of code, this method will return
	 *          <code>"000000"</code>.
	 * @outparam A String that represents the Hex Value of the Object Code for
	 *           the given line number.
	 * @errorstested See JUnit test cases
	 * @errorsgenerated See errata report
	 * @createdate 11/5/09
	 * @modlog <p>
	 *         <ul>
	 *         Who/When/Why
	 *         <li>
	 *         </ul>
	 *         Coding Standards Met: "Signed Code Leader(Jaron)"
	 *         <p>
	 *         Testing Standards Met: "Signed Test Leader(Jamie)"
	 */
	public static String returnObjectCode(Integer lineNumber) {
		if (lineNumberArray.size() != 0 && objectCodeArray.size() != 0
				&& lineNumberArray.contains(lineNumber)) {
			Integer lineNumberIndex = lineNumberArray.indexOf(lineNumber);
			String objectCodeAsBin = objectCodeArray.get(lineNumberIndex);
			Main.appendDebugText(objectCodeArray.get(lineNumberIndex));
			if (objectCodeAsBin.contains("n/a") && objectCodeAsBin.length() > 3){
				objectCodeAsBin = objectCodeAsBin.substring(3);
			}
			Integer valueOfObjectCodeBin = Integer.valueOf(objectCodeAsBin, 2);
			String hexValue = Integer.toHexString(valueOfObjectCodeBin);
			while (hexValue.length() < 6) {
				hexValue = "0" + hexValue;
			}
			Main.appendDebugText(hexValue);
			return hexValue;
		} else if (!lineNumberArray.contains(lineNumber)) {
			return "------";
		} else {
			return "000000";
		}
	}

}
